// 抽象工厂方法模式
// 针对产品族开发，是符合开闭原则的，即水果种类不变，国家增加或减少
package main

import "fmt"

// -----抽象层-----

type AbstractApple interface {
	ShowApple()
}
type AbstractBanana interface {
	ShowBanana()
}
type AbstractPear interface {
	ShowPear()
}

// AbstractFactory 抽象的工厂
type AbstractFactory interface {
	CreateApple() AbstractApple
	CreateBanana() AbstractBanana
	CreatePear() AbstractPear
}

// -----实现层-----
// 中国产品族------------------------------------------------------------

type ChinaApple struct{}

func (ca *ChinaApple) ShowApple() {
	fmt.Println("中国苹果")
}

type ChinaBanana struct{}

func (cb *ChinaBanana) ShowBanana() {
	fmt.Println("中国香蕉")
}

type ChinaPear struct{}

func (cp *ChinaPear) ShowPear() {
	fmt.Println("中国梨")
}

type ChinaFactory struct{}

func (cf *ChinaFactory) CreateApple() AbstractApple {
	return &ChinaApple{}
}
func (cf *ChinaFactory) CreateBanana() AbstractBanana {
	banana := new(ChinaBanana)
	return banana
}
func (cf *ChinaFactory) CreatePear() AbstractPear {
	var pear AbstractPear
	pear = new(ChinaPear)
	return pear
}

// 日本产品族------------------------------------------------------------

type JapanApple struct{}

func (ja *JapanApple) ShowApple() {
	fmt.Println("日本苹果")
}

type JapanBanana struct{}

func (jb *JapanBanana) ShowBanana() {
	fmt.Println("日本香蕉")
}

type JapanPear struct{}

func (jp *JapanPear) ShowPear() {
	fmt.Println("日本梨")
}

type JapanFactory struct{}

func (jf *JapanFactory) CreateApple() AbstractApple {
	return &JapanApple{}
}
func (jf *JapanFactory) CreateBanana() AbstractBanana {
	banana := new(JapanBanana)
	return banana
}
func (jf *JapanFactory) CreatePear() AbstractPear {
	var pear AbstractPear
	pear = new(JapanPear)
	return pear
}

// -----逻辑层-----

func main() {
	// 需求：需要中国的苹果、香蕉、梨

	// 易读不易写
	// 1-创建一个中国工厂
	var chinaFactory AbstractFactory
	fmt.Println(chinaFactory)
	chinaFactory = new(ChinaFactory)
	fmt.Println(chinaFactory)
	// 2-生成苹果
	var chinaApple AbstractApple
	chinaApple = new(ChinaApple)
	chinaApple.ShowApple()
	// 3-生成香蕉
	var chinaBanana AbstractBanana
	chinaBanana = new(ChinaBanana)
	chinaBanana.ShowBanana()
	// 4-生成梨子
	var chinaPear AbstractPear
	chinaPear = new(ChinaPear)
	chinaPear.ShowPear()

	//// 易写不易读
	//chinaFactory := &ChinaFactory{}
	//chinaApple := chinaFactory.CreateApple()
	//chinaBanana := chinaFactory.CreateBanana()
	//chinaPear := chinaFactory.CreatePear()
	//
	//fmt.Println(chinaApple)
	//fmt.Println(chinaBanana)
	//fmt.Println(chinaPear)
	//
	//chinaApple.ShowApple()
	//chinaBanana.ShowBanana()
	//chinaPear.ShowPear()
}
